/*
 * liwe.js
 *
 * Copyright (C) 2006 - OS3 srl - http://www.os3.it
 *
 * Written by: Fabio Rotondo - fabio.rotondo@os3.it
 *
 * This is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation;
 * version 2 of the License ONLY.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public
 * License along with this software; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * NOTE: this is the GPL version of the library. If you want to include this 
 *       library inside a CLOSED SOURCE / PROPRIETARY software, you need 
 *       to purchase a COMMERCIAL LICENSE. See http://www.os3.it/license/
 *       for more info.
 */

/*
 *
 *	2009-04-16:	- Added the ``strong_debug`` flag to the liwe base class (default to ``false``).
 *
 *
 *	2009-03-06:	- $() and $v() are now here and not in utils.js
 *			- $() now can have a second optional argument to set the innerHTML.
 */

function is_nodejs ()
{
	return typeof ( exports ) !== 'undefined';
}

// {{{ base docs
/**
liwe.js
=======
**/
// }}}

// PUBLIC: liwe
var liwe = {};
liwe.utils = {};
liwe.fx = {};

liwe.strong_debug = false;

// Library base
liwe._libbase = "";

liwe.ajax_url = "/ajax.php";

// Try to be compatible with other browsers
// Only use firebug logging when available
// (this code is a modified version of firebugx.js, written
// by Joe Hewitt)
if ( ! is_nodejs () )
{
	if ( ! window [ "console" ] ) window.console = {};

	try
	{
		liwe._console = window.console [ "debug" ];
		if ( window.console.__noSuchMethod__ ) liwe._console = null;
	} catch ( e ) {
		liwe._console = null;
	}

	if ( ! liwe._console )
	{
		var names = [ "assert", "clear", "count", "debug", "dir", "dirxml", "error", "exception",
			      "group", "groupCollapsed", "groupEnd", "info", "log", "memoryProfile", "memoryProfileEnd",
			      "profile", "profileEnd", "table", "time", "timeEnd", "trace", "warn" ];

		for ( var i = 0; i < names.length; ++i )
		{
			window.console [ names [ i ] ] = function () {};
		}
	}

	liwe.set_libbase = function ( libbase_url )
	{
		if ( libbase_url )
		{
			liwe._libbase = libbase_url;
			return;
		}

		var scripts = document.getElementsByTagName ( "script" );
		var l = scripts.length;
		var t, s, pos, path = "";

		for ( t = 0; t < l; t ++ )
		{
			s = scripts [ t ].src;

			if ( ! s ) continue;

			if ( s.match ( /liwe.*js/ ) )
			{
				s = s.replace ( /.*os3phplib.send_gzip.php.fname=/, "" );
				pos = s.lastIndexOf ( "/" );
				if ( pos != -1 ) path = s.slice ( 0, pos + 1 );
			}
		}

		if ( path ) liwe._libbase = path;
		else liwe._libbase = "/os3jslib";
	};

	liwe.set_libbase ();

	liwe.browser = {};

	liwe.browser.version = navigator.appVersion;
	liwe.browser.has_dom = document.getElementById ? 1 : 0;
	liwe.browser.ie = ( typeof window [ "ActiveXObject" ] != "undefined" ); //window.ActiveXObject != null );
	liwe.browser.gecko = ( navigator.userAgent.toLowerCase().indexOf ( "gecko" ) != -1 ) ? 1 : 0;
	liwe.browser.opera = ( navigator.userAgent.toLowerCase().indexOf ( "opera" ) != -1 ) ? 1 : 0;

}

// =============================================================================
// UTILS
// =============================================================================
liwe.utils.WAIT_TIMEOUT = 2000; // Milli seconds
liwe.utils.WAIT_TIME = 50; // Milli seconds

liwe.utils.wait_def = function ( name, cback, vars, time )
{
	if ( ! liwe.utils.is_def ( name ) ) 
	{
		if ( ! time ) time = 0;
		if ( time > liwe.utils.WAIT_TIMEOUT )
		{
			if ( liwe.strong_debug ) alert ( "Failed: " + name );
			return;
		}

		setTimeout ( function () { liwe.utils.wait_def ( name, cback, vars, time + liwe.utils.WAIT_TIME ); }, liwe.utils.WAIT_TIME );
	} else {
		if ( typeof ( cback ) != 'object' ) cback ( vars );
	}
};

liwe.utils.append_js = function ( script_file, cback )
{
	var head = document.getElementsByTagName ( "head" ) [ 0 ];
	var new_script = document.createElement ( "script" );

	new_script.src = script_file;
	new_script.type = "text/javascript";

	if ( cback )
	{
		function wrapped ()
		{
			liwe.events.del ( new_script, wrapped );
			cback ();
		}
		liwe.events.add ( new_script, 'load', wrapped );
	}

	head.appendChild ( new_script );
};


liwe.utils.is_def = function ( name )
{
	var is_def = false;
	var l;

	if ( typeof name == "string" )
	{
		var items = name.split ( "." );
		var s = '';

		s = items [ 0 ];
		l = items.length;

		for ( t = 0; t < l; t ++ )
		{
			// console.debug ( "Check for: " + s );
			eval ( "is_def = ( typeof ( " + s + " ) != 'undefined' );" );
			if ( ! is_def ) return false;
			if ( ! items [ t + 1 ] ) break;

			s += "." + items [ t + 1 ];
		}
		return true;
	}

	var t;
	var n;

	l = name.length;

	for ( t = 0; t < l; t ++ )
	{
		n = name [ t ];
		eval ( "is_def = ( typeof ( " + n + " ) != 'undefined' );" );

		if ( ! is_def ) return false;
	}

	return true;
};

liwe.cfg = {};

// =============================================================================
// POSTLOADER
// =============================================================================

liwe.postload = {};

// The time (in millis) before a specified file is timedout
liwe.postload.WAIT_TIMEOUT = 30000; // 30 seconds (time is in millis)

// Millis to check for a specified file
liwe.postload.WAIT_TIME = 50; // 50 milli seconds
liwe.postload.events = {};

// This event is fired when a SINGLE SCRIPT has been loaded
// cback: script_loaded ( script_name )
liwe.postload.events [ 'script_load' ] = null;	

// This event is fired whenever PostLoader thinks it is good to
// update your load status info
// cback: script_update ( items_loaded, tot_items )
liwe.postload.events [ 'update' ] = null;

// This event is fired when PostLoader has finished to load
// ALL scripts defined.
// cback: script_completed ()
liwe.postload.events [ 'completed' ] = null;

/* FILES fields values:
#
#	0 - priority
#	1 - file name
#	2 - check_for
#	3 - cback
#	4 - vars
#	5 - is loaded
*/
liwe.postload._files = [];
liwe.postload._loaded_files = 0;

liwe.postload.add = function ( fname, check_for, pri, cback, vars )
{
	if ( ! pri ) pri = 1;

	if ( liwe.utils.is_def ( check_for ) ) return;

	liwe.postload._files.push ( [ pri, fname, check_for, cback, vars, 0 ] );
};

liwe.postload.load = function ()
{
	var t, l, itm;

	liwe.postload._files.sort ();

	l = liwe.postload._files.length;

	// keep count of loaded files
	liwe.postload._loaded_files = 0;

	for ( t = 0; t < l; t ++ )
	{
		itm = liwe.postload._files [ t ];
		// Files already in memory are skipped
		if ( itm [ 5 ] ) liwe.postload._loaded ( t ); 

		liwe.utils.append_js ( itm [ 1 ] );
		liwe.utils.wait_def ( itm [ 2 ], liwe.postload._loaded, t );
	}
};

liwe.postload._loaded = function ( pos )
{
	liwe.postload._loaded_files += 1;

	var itm = liwe.postload._files [ pos ];

	itm [ 5 ] = 1;

	if ( liwe.postload.events [ 'script_loaded' ] )
		liwe.postload.events [ 'script_loaded' ] ( itm [ 1 ] );

	if ( itm [ 3 ] ) itm [ 3 ] ( itm [ 4 ] );

	if ( liwe.postload.events [ 'update' ] )
		liwe.postload.events [ 'update' ] ( liwe.postload._loaded_files, liwe.postload._files.length );

	if ( ! ( liwe.postload._files.length - liwe.postload._loaded_files ) )
		if ( liwe.postload.events [ 'completed' ] ) liwe.postload.events [ 'completed' ] ();
};


liwe._clear_dom = function ( e )
{
	var i, l = e.childNodes.length;
	for ( i = 0; i < l; i ++ )
	{
		var el = e.childNodes [ i ];

		//PULIZIA
		var v;
		for ( v in el )
		{
			if ( v.charAt ( 0 ) != "_" ) continue;

			console.debug ( v );

			if ( v == "_listeners" )
			{
				var listeners = [].concat ( el [ v ] );
				var vi, vl = listeners.length;
				for ( vi = 0; vi < vl; vi ++ )
				{
					var lid = listeners [ vi ];
					var rec = _all [ lid ];
					if ( rec ) liwe.events.del ( rec.target, rec.type, rec.listener );
				}
			}

			try
			{
				el [ v ] = null;
			}
			catch (e)
			{
			}
		} 

		liwe._clear_dom ( el );
	}
};

// {{{ $( obj_name, [ new_inner_html ] )
/**
.. function:: $( obj_name, [new_inner_html] )

   Fetch the object with id ``obj_name`` inside the DOM and returns it.
   If ``new_inner_html`` has been specified, content of the object corresponding to ``obj_name`` is also updated to
   ``new_inner_html`` value. 

   :param obj_name: the object id name
   :param new_inner_html: (optional) the new inner html value to assign to the object ``obj_name`` (if it exists)
	
   .. note::
	``new_inner_html`` is a string of HTML text. If the object ``obj_name`` actually exists, its 
	contents will be replaced using standard DOM ``obj.innerHTML = txt`` method.
**/
function $ ( name, inner_html, warn )
{
	if ( ! name ) return null;

	var e = $el ( name );

	if ( ! e ) 
	{
		if ( warn ) console.warn ( "Element: %s not found", name );
		return null;
	}

	if ( typeof inner_html == "undefined" )
		return e;

	// liwe._clear_dom ( e );

	e.innerHTML = inner_html;
	return e;
}
// }}}
// {{{ $v ( name, def_val )
/**
.. function:: $v ( obj_name, [def_val] )

   Fetch the value contained inside ``obj_name`` object. This function is usefull with ``<form>`` elements such as
   ``<input>``, ``<textarea>`` and so on.
   You can specify a ``def_val`` that will be returned if ``obj_name`` does not exists or ``obj_name`` value is not
   set at all (``undefined``).

   :param obj_name: name of the object to fetch value from.
   :param def_val: (optional) value to be returned if ``obj_name`` is missing or with no value.
**/
function $v ( name, def_val )
{
	var d = document.getElementById ( name );
	if ( ! d ) return def_val;

	if ( ( d.type == 'select' ) || ( d.type == 'select-one' ) )
	{
		if ( d.selectedIndex >= 0 ) 
			return d.options [ d.selectedIndex ].value;
		else
			return null;
	}

	return d.value;
}
// }}}

// {{{ function $el ( el )
/**
.. function:: $el ( el_name )

   Returns the element with the ``el_name`` ID.
   If ``el_name`` is not a string, returns the ``el_name`` itself.

   :param el_name: the element name
**/
function $el ( el )
{
	if ( typeof el != "string" ) return el;

	return document.getElementById ( el );
}
// }}}
//

if ( is_nodejs () ) module.exports = liwe;
